package com.block.datapush.special.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.account.enums.ActionTypeEnum;
import com.block.account.model.dto.EntryAccountDTO;
import com.block.account.service.impl.AccountItemSpecialServiceImpl;
import com.block.common.annotate.ExceptionLog;
import com.block.common.model.dto.CountInfoDTO;
import com.block.common.service.ICountCommonService;
import com.block.common.service.LogFactory;
import com.block.datapush.model.result.ApiPushResult;
import com.block.datapush.model.result.SpePushResut;
import com.block.datapush.service.IMemberPushOrderInfoService;
import com.block.datapush.special.enums.OrderStatusEnum;
import com.block.datapush.special.factory.InfoTypeFactory;
import com.block.datapush.special.service.ISpecialCostomInfoService;
import com.block.datapush.special.service.ISpecialCostomUserInfoService;
import com.block.datapush.special.service.ISpecialDataApiInfoService;
import com.block.datapush.special.service.ISpecialDataInfoService;
import com.block.db.entity.MemberExtInfo;
import com.block.db.entity.MemberPushOrderInfo;
import com.block.db.entity.SpecialCostomInfo;
import com.block.db.entity.SpecialCostomItemInfo;
import com.block.db.mapper.MemberExtInfoMapper;
import com.block.db.mapper.MemberPushOrderInfoMapper;
import com.block.db.mapper.SpecialCostomInfoMapper;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 
 * @since 2022-09-15
 */
@Service
public class SpecialCostomInfoServiceImpl extends ServiceImpl<SpecialCostomInfoMapper, SpecialCostomInfo> implements ISpecialCostomInfoService {

    private static Logger log = LogFactory.getPushLog();

    @Value("${market.protocol.hostUrl}")
    private String protocolHostUrl;

    @Autowired
    ISpecialDataInfoService specialDataInfoService;
    @Autowired
    ISpecialCostomUserInfoService specialCostomUserInfoService;
    @Autowired
    ISpecialDataApiInfoService specialDataApiInfoService;
    @Autowired
    TransactionTemplate transactionTemplate;
    @Autowired
    ICountCommonService countCommonService;
    @Autowired
    AccountItemSpecialServiceImpl accountItemSpecialService;
    @Autowired
    IMemberPushOrderInfoService memberPushOrderInfoService;
    @Resource
    MemberPushOrderInfoMapper memberPushOrderInfoMapper;
    @Resource
    MemberExtInfoMapper memberExtInfoMapper;

    /**
     * 机构推送完成的逻辑
     * 将某个用户推送给某个机构
     * 根据商户设置的任务信息
     */
    @Override
    @ExceptionLog(key = "#costomId", bizType = "机构推送", bizName = "数据推送")
    public SpePushResut checkAndRegisterUser(SpecialCostomItemInfo itemInfo, MemberExtInfo memberExtInfo) throws Exception {

        SpePushResut spePushResut = new SpePushResut();

        SpecialCostomInfo costomInfo = this.getById(itemInfo.getInfoId());

        spePushResut.setSpeInfoId(costomInfo.getId());
        spePushResut.setSpeInfoType(costomInfo.getInfoType());
        spePushResut.setSpeItemInfoId(itemInfo.getId());
        spePushResut.setSpeInfoName(costomInfo.getName());
        spePushResut.setSpeItemAmount(itemInfo.getPriceAmount());
        spePushResut.setPushSuccess(false);
        spePushResut.setCompanyName(costomInfo.getCompanyName());
        spePushResut.setCompanyUser(costomInfo.getCompanyUser());
        spePushResut.setCompanyPhone(costomInfo.getCompanyPhone());

        ApiPushResult apiPushResult = InfoTypeFactory.getService(costomInfo.getInfoType()).checkAndRegisterUser(costomInfo, itemInfo, memberExtInfo);
        spePushResut.setPushSuccess(apiPushResult.isSuccess());
        spePushResut.setSettleFlag(apiPushResult.isSettleFlag());
        spePushResut.setSkipUrl(apiPushResult.getSkipUrl());
        spePushResut.setMessage(apiPushResult.getMessage());
        spePushResut.setExtData(apiPushResult.getOrderNo());

        log.info("【机构推送】推送完成【pushResult】{}【infoType】{}【itemId】{}【uid】{}",
                spePushResut.isPushSuccess(), costomInfo.getInfoType(), itemInfo.getId(), memberExtInfo.getUid());

        // 更新账户余额
        if (spePushResut.isSettleFlag()){
            /**
             * 机构收益统计
             */
            CountInfoDTO countInfoDTO = new CountInfoDTO(memberExtInfo.getChannelCode());
            countInfoDTO.setSpePushCount(1);
            countInfoDTO.setSpePushAmount(spePushResut.getSpeItemAmount());
            countCommonService.calculateDataInfo2(countInfoDTO);

            String billDateInfo = LocalDate.now().toString();

            EntryAccountDTO entryAccountDTO = new EntryAccountDTO();
            entryAccountDTO.setInfoId(String.valueOf(itemInfo.getInfoId()));
            entryAccountDTO.setBillDateInfo(billDateInfo);
            entryAccountDTO.setActionType(ActionTypeEnum.XH.getValue());
            entryAccountDTO.setChangeAmount(BigDecimal.ZERO.subtract(spePushResut.getSpeItemAmount()));
            entryAccountDTO.setExtData(spePushResut.getExtData());
            entryAccountDTO.setOperatorId("0");
            entryAccountDTO.setOperatorName("system");

            accountItemSpecialService.entryAccountInfo(entryAccountDTO);
        }
        // 返回更新结果
        return spePushResut;
    }


    /**
     * 机构撞库 生成订单信息
     */
    @Override
    @ExceptionLog(key = "#costomId", bizType = "机构检测推送", bizName = "数据检测推送")
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public SpePushResut checkUser(SpecialCostomItemInfo itemInfo, MemberExtInfo memberExtInfo) throws Exception {

        // 查询用户信息
        SpecialCostomInfo costomInfo = this.baseMapper.getEntryByIdLock(itemInfo.getInfoId());

        // 保存推送订单信息
        MemberPushOrderInfo pushOrderInfo = new MemberPushOrderInfo();
        pushOrderInfo.setDateInfo(LocalDate.now().toString());
        pushOrderInfo.setInfoId(itemInfo.getInfoId());
        pushOrderInfo.setInfoType(itemInfo.getInfoType());
        pushOrderInfo.setInfoName(costomInfo.getName());
        pushOrderInfo.setUid(memberExtInfo.getUid());
        pushOrderInfo.setTaskId(itemInfo.getId());
        pushOrderInfo.setPriceAmount(itemInfo.getPriceAmount());
        pushOrderInfo.setStatus(OrderStatusEnum.INIT.getValue());
        if (ObjectUtil.isNotEmpty(costomInfo.getDeptId())){
            pushOrderInfo.setDeptId(Long.valueOf(costomInfo.getDeptId()));
        }
        memberPushOrderInfoService.save(pushOrderInfo);

        // 构造推送信息
        SpePushResut spePushResut = new SpePushResut();

        spePushResut.setOrderNo(String.valueOf(pushOrderInfo.getId()));
        spePushResut.setSpeInfoId(costomInfo.getId());
        spePushResut.setSpeInfoType(costomInfo.getInfoType());
        spePushResut.setSpeItemInfoId(itemInfo.getId());
        spePushResut.setSpeInfoName(costomInfo.getName());
        spePushResut.setSpeItemAmount(itemInfo.getPriceAmount());
        spePushResut.setPushSuccess(false);
        spePushResut.setCompanyUser(costomInfo.getCompanyUser());
        spePushResut.setCompanyPhone(costomInfo.getCompanyPhone());
        spePushResut.setCompanyName(costomInfo.getCompanyName());

        // 执行撞库操作
        ApiPushResult apiPushResult = InfoTypeFactory.getService(costomInfo.getInfoType()).checkUser(costomInfo, itemInfo, memberExtInfo);
        log.info("【机构撞库】撞库完成【apiPushResult】{}【infoType】{}【itemId】{}【uid】{}",
                JSON.toJSONString(apiPushResult), costomInfo.getInfoType(), itemInfo.getId(), memberExtInfo.getUid());
        spePushResut.setPushSuccess(apiPushResult.isSuccess());
        spePushResut.setSkipUrl(apiPushResult.getSkipUrl());
        spePushResut.setMessage(apiPushResult.getMessage());

        // 更新推送订单信息
        MemberPushOrderInfo updateEntity =new MemberPushOrderInfo();
        updateEntity.setId(pushOrderInfo.getId());
        updateEntity.setPushId(apiPushResult.getOrderNo());
        if (apiPushResult.isSuccess()){
            updateEntity.setStatus(OrderStatusEnum.WAIT_PUSH.getValue());
        }else{
            updateEntity.setStatus(OrderStatusEnum.CHECK_ERROR.getValue());
        }
        memberPushOrderInfoService.updateById(updateEntity);

        String protocolUrl = StrUtil.format(protocolHostUrl, pushOrderInfo.getId());
        // 授权协议信息
        spePushResut.setProtocolUrl(protocolUrl);

        // 返回更新结果
        return spePushResut;
    }

    /**
     * 根据订单信息 进件操作
     * @return
     * @throws Exception
     */
    @Override
    @ExceptionLog(key = "#costomId", bizType = "机构检测推送", bizName = "数据检测推送")
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public SpePushResut registerUser(String orderNo) throws Exception {

        SpePushResut spePushResut = new SpePushResut();
        spePushResut.setPushSuccess(false);
        MemberPushOrderInfo pushOrderInfo = memberPushOrderInfoMapper.getEnityByIdLock(orderNo);
        if (ObjectUtil.isEmpty(pushOrderInfo)){
            // 信息为空
            spePushResut.setMessage("订单信息为空");
            return spePushResut;
        }

        if (!ObjectUtil.equals(pushOrderInfo.getStatus(), OrderStatusEnum.WAIT_PUSH.getValue())){
            // 订单状态错误
            spePushResut.setMessage("订单状态错误");
            return spePushResut;
        }

        // 查询用户信息
        SpecialCostomInfo costomInfo = this.baseMapper.getEntryByIdLock(pushOrderInfo.getInfoId());
        MemberExtInfo memberExtInfo = this.memberExtInfoMapper.selectById(pushOrderInfo.getUid());

        // 构造返回信息
        spePushResut.setSpeInfoId(pushOrderInfo.getInfoId());
        spePushResut.setSpeInfoType(pushOrderInfo.getInfoType());
        spePushResut.setSpeItemInfoId(pushOrderInfo.getTaskId());
        spePushResut.setSpeInfoName(pushOrderInfo.getInfoName());
        spePushResut.setSpeItemAmount(pushOrderInfo.getPriceAmount());

        log.info("【机构进件】开始进件【orderNo】{}【infoType】{}", pushOrderInfo.getId());
        ApiPushResult apiPushResult = InfoTypeFactory.getService(costomInfo.getInfoType()).registerUser(costomInfo, pushOrderInfo, memberExtInfo);
        log.info("【机构进件】进件完成【orderNo】{}【apiPushResult】{}", pushOrderInfo.getId(), JSON.toJSONString(apiPushResult));

        spePushResut.setPushSuccess(apiPushResult.isSuccess());
        spePushResut.setSettleFlag(apiPushResult.isSettleFlag());
        spePushResut.setSkipUrl(apiPushResult.getSkipUrl());
        spePushResut.setMessage(apiPushResult.getMessage());

        MemberPushOrderInfo updateEntity = new MemberPushOrderInfo();
        updateEntity.setId(pushOrderInfo.getId());
        updateEntity.setStatus(OrderStatusEnum.FAILED.getValue());
        // 更新订单信息
        if (apiPushResult.isSuccess()){
            updateEntity.setStatus(OrderStatusEnum.SUCCESS.getValue());
        }
        memberPushOrderInfoService.updateById(updateEntity);

        //如果进行结算，
        // 更新账户余额
        if (apiPushResult.isSettleFlag()){
            /**
             * 机构收益统计
             */
            CountInfoDTO countInfoDTO = new CountInfoDTO(memberExtInfo.getChannelCode());
            countInfoDTO.setSpePushCount(1);
            countInfoDTO.setSpePushAmount(spePushResut.getSpeItemAmount());
            countCommonService.calculateDataInfo2(countInfoDTO);

            String billDateInfo = LocalDate.now().toString();

            EntryAccountDTO entryAccountDTO = new EntryAccountDTO();
            entryAccountDTO.setInfoId(String.valueOf(pushOrderInfo.getInfoId()));
            entryAccountDTO.setBillDateInfo(billDateInfo);
            entryAccountDTO.setActionType(ActionTypeEnum.XH.getValue());
            entryAccountDTO.setChangeAmount(BigDecimal.ZERO.subtract(spePushResut.getSpeItemAmount()));
            entryAccountDTO.setExtData(spePushResut.getExtData());
            entryAccountDTO.setOperatorId("0");
            entryAccountDTO.setOperatorName("system");

            accountItemSpecialService.entryAccountInfo(entryAccountDTO);
        }

        // 返回更新结果
        return spePushResut;
    }

}
